using System;
using System.Collections.Generic;
using System.Linq;

namespace Windy.OpenLink.ObjectPools
{
    public class ObjectPool : IObjectPool
    {
        #region Constructors

        public ObjectPool()
        {
            Objects = new Dictionary<string, object>();
        }

        #endregion Constructors

        #region Internal Members

        protected Dictionary<string, object> Objects;

        #endregion Internal Members

        #region IObjectPool Members

        public virtual object this[string id]
        {
            get
            {
                return Get<object>(id);
            }
            set
            {
                Set<object>(id, value);
            }
        }

        public virtual bool TryGet(string id, out object value)
        {
            return Objects.TryGetValue(id, out value);
        }

        public virtual int Count { get { return Objects.Count; } }

        public virtual T Get<T>(string id)
            where T : class
        {
            object value;

            if (TryGet(id, out value))
            {
                return value as T;
            }
            else
            {
                return null;
            }
        }

        public virtual void Set<T>(string id, T value)
            where T : class
        {
            if (Objects.ContainsKey(id))
            {
                Objects[id] = value;
            }
            else
            {
                Objects.Add(id, value);
            }
        }

        public virtual IEnumerable<string> Ids
        {
            get { return this.Objects.Keys; }
        }

        public virtual bool IsExist(string id)
        {
            return Objects.ContainsKey(id);
        }

        public virtual bool Remove(string id)
        {
            var disposable = Get<IDisposable>(id);
            if (disposable != null)
                disposable.Dispose();

            return Objects.Remove(id);
        }

        public virtual bool RemoveTree(string id, bool includeRoot = true)
        {
            bool result = false;

            foreach (var fo in Objects.Keys.ToArray())
            {
                if (fo.StartsWith(id))
                {
                    if (!includeRoot && fo == id)
                        continue;

                    result |= Remove(fo);
                }
            }

            return result;
        }

        public virtual IEnumerable<KeyValuePair<string, object>> AsEnumerable()
        {
            return Objects;
        }

        #endregion IObjectPool Members
    }
}
